﻿using System;
using System.Collections.Generic;
using System.Reflection;
using UnityEngine;

namespace Core
{
    public partial class UISystem
    {
        private Dictionary<long, List<Component>> fieldDict = new();

        public void ParseUIField(Component parser, GameObject root_obj)
        {
            if (fieldDict.ContainsKey(parser.InstanceId))
            {
                log.err($"ParseUIField Parser Is Already Exist; parser={parser}");
                return;
            }

            GameObject rootObj = root_obj;

            Type thisType = parser.GetType();

            FieldInfo[] fs = thisType.GetFields(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance);
            Type targetType = typeof(UIFieldAttribute);
            foreach (FieldInfo f in fs)
            {
                if (!f.IsDefined(targetType, false))
                {
                    continue;
                }

                var attrs = f.GetCustomAttributes(targetType, false);
                if (attrs.Length == 0 || attrs[0] is not UIFieldAttribute attr)
                {
                    continue;
                }

                Transform tf = rootObj.transform;
                if (!string.IsNullOrEmpty(attr.Path))
                {
                    tf = rootObj.transform.Find(attr.Path);
                }

                if (tf == null)
                {
                    if (attr.Ignore == false)
                    {
                        log.err($"Can't find {attr.Path} in UI {rootObj.name}");
                    }
                    continue;
                }

                GameObject gameObj = tf.gameObject;

                Type f_type = f.FieldType;

                if (f_type == null)
                {
                    continue;
                }

                if (f_type == gameObj.GetType())
                {
                    f.SetValue(parser, gameObj);
                    continue;
                }

                //var com = gameObj.GetComponent(f_type);
                var com = G.Factory.Create(f_type, gameObj);
                if (com == null)
                {
                    log.err($"Can't find component with type {f_type.Name} in widget {attr.Path} in UI {rootObj.name}");
                    continue;
                }

                if (com is UIWidget widget)
                {
                    widget.Init();
                }
                if (com is UICloseButton btn_close)
                {
                    btn_close.Set(parser as Window);
                    btn_close.Set(parser as UIWidget);
                }

                f.SetValue(parser, com);

                RecordUIField(parser, com);
            }
        }

        private void RecordUIField(Component parser, Component field)
        {
            if (parser == null || parser.InstanceId == 0 || field == null)
            {
                return;
            }
            var id = parser.InstanceId;
            if (fieldDict.ContainsKey(id) == false)
            {
                fieldDict[id] = new List<Component>();
            }
            var lst = fieldDict[id];
            lst.Add(field);
        }

        public void DisposeUIField(Component parser)
        {
            if (parser == null || parser.InstanceId == 0)
            {
                return;
            }
            var id = parser.InstanceId;
            if (fieldDict.ContainsKey(id) == false)
            {
                return;
            }
            var fields = fieldDict[id];
            foreach (var field in fields)
            {
                field.Dispose();
            }
            fields.Clear();

        }
    }
}
